<template>
	<div class="edit-drawer" :style="{width: width+'px'}">
		<div class="head">
			<div class="opear">
				<div>
					<span>{{apiTitle}}</span>
				</div>
				<ul>
					<li >
						<button class="code-run-btn" @click="runCode">运行</button>
					</li>
					<li >
						<button :class="codeRestbtn" @click="restCode">恢复</button>
					</li>
				</ul>
			</div>
		</div>
		<div class="body">
			<div class="edit" >
				<el-scrollbar height="100%">
					<codemirror
						v-model="code"
						mode="htmlmixed"
						placeholder=""
						scrollbarStyle="null"
						autoCloseBrackets=true
						matchBrackets=true
						showCursorWhenSelecting=true
						autoCloseTags=true
						:autofocus="true"
						:indent-with-tab="true"
						:tabSize="2"
						:extensions="extensions"
						:lineWrapping="true"
						@ready="log('ready', $event)"
						@change="log('change', $event)"
						@focus="log('focus', $event)"
						@blur="log('blur', $event)"
					/>
				</el-scrollbar>
			</div>
			<div class="log">
				<div class="head">
					<div>
						<span>Logs</span>
						<div>
							<span @click="clearLogs">清空</span>
						</div>
					</div>
				</div>
				
				<div class="log-content">
					  <el-scrollbar height="100%">
						  <ul>
						  	<li v-for="p in logRecords" class="log-li">
						  		<pre v-html="p"></pre>
						  	</li>
						  </ul>
					  </el-scrollbar>
				</div>
				
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
	import { Codemirror } from "vue-codemirror";
	import { javascript } from "@codemirror/lang-javascript";
	import { oneDark } from "@codemirror/theme-one-dark";
	const apiTitle=ref('调试区');
	const width=ref(0);
	const logRecords=ref([]);
	const codeRestbtn=ref('code-rest-btn disable');
	const code = ref();
	const extensions = [javascript(), oneDark];
	const defaultCode = ref();
	
	//json 格式化Html
	const syntaxHighlight=(json:any)=> {
		if (typeof json != 'string') {
			json = JSON.stringify(json, undefined, 2);
		}
		json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
		return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
			var cls = 'number';
			if (/^"/.test(match)) {
				if (/:$/.test(match)) {
					cls = 'key';
				} else {
					cls = 'string';
				}
			} else if (/true|false/.test(match)) {
				cls = 'boolean';
			} else if (/null/.test(match)) {
				cls = 'null';
			}
			return '<span class="' + cls + '">' + match + '</span>';
		});
	}
	
	const addLog = (e:any) => {
		if(logRecords.value.length>5){
			logRecords.value.unshift(syntaxHighlight(e));
			logRecords.value.pop()
		}else{
			logRecords.value.unshift(syntaxHighlight(e));
		}
	};
	
	const log=(type:any,e:Event)=>{
		if('change'==type){
			if(defaultCode.value==code.value){
				codeRestbtn.value="code-rest-btn disable";
			}else{
				codeRestbtn.value="code-rest-btn";
			}
		}
	}
	
	const runCode = () => {
		try{
			
			if(code.value){
				eval(code.value);
			}
			else{
				ElMessage({
				    message: '无可执行代码.',
				    type: 'warning',
				  })
			}
			
		}catch(e){
			ElMessage.error('执行异常.')
			console.error(e)
		}
	};
	
	const restCode = () => {
		code.value=defaultCode.value
		codeRestbtn.value="code-rest-btn disable";
	};
	
	const clearLogs=()=>{
		logRecords.value=[];
	}
	
	const setCode=(data:any)=>{
		code.value=data.content
		apiTitle.value=data.name
	}
	
	const collapse=(value:boolean)=>{
		if(value){
			width.value=400;
		}else{
			width.value=0;
		}
		
	}
	defineExpose({
		setCode,collapse,addLog
	});
	
</script>


<style  scoped>
	.edit-drawer{
		height: 100%;
		top: 0;
		bottom: 0;
		right: 0;
		width: 0px;
		border-left: 1px solid #373c54;
		position: absolute;
		z-index: 1;
		background-color:  #212332;
		overflow: hidden;
		-moz-user-select:none; /*火狐*/
		-webkit-user-select:none; /*webkit浏览器*/
		-ms-user-select:none; /*IE10*/
		-khtml-user-select:none; /*早期浏览器*/
		user-select:none;
		transition: all .3s ease;
		>.head{
			border-bottom: 1px solid #373c54;
			height: 40px;
			background-color: #2a2d3e;
			>.opear{
				display: flex;
				height: 100%;
				width: 100%;
				display: flex;
				justify-content: space-between;
				align-items: center;
				align-content: center;
				flex-direction: row;
				flex-wrap: nowrap;
				>div{
					padding: 0.3125rem;
					>span{
						border-left-width: 3px!important;
						padding-left: 8px!important;
						height: 16px;
						line-height: 17px;
						font-size: 13px;
						color: #ccc;
						-webkit-box-sizing: border-box;
						box-sizing: border-box;
						text-overflow: ellipsis;
						overflow: hidden;
						white-space: nowrap;
						width: 250px;
						display: block;
						border-left: 2px solid #0080ff;
						margin-left: 8px;
						padding-left: 3px;
					}
				}
				>ul{
					>li{
						list-style: none;
						float: left;
						padding-right:3px;
						>button{
							width: 50px;
							height: 24px;
							font-size: 13px;
							color: #ccc;
						}
						
						>.code-run-btn{
							background-color: rgba(63, 163, 255, 0.5490196078) !important;
							border: none;
							margin-right: 0.625rem;
							cursor:pointer;
						}
						>.code-run-btn:hover{
							background-color: rgba(63, 163, 255, 0.9) !important;
							color: white;
						} 
						>.code-rest-btn{
							background: #EE7752;
							border: none;
							color: #fff;
							cursor:pointer;
						}
						>.code-rest-btn:hover{
						   background: #d56a49;
						}
						>.code-rest-btn.disable{
							background: #a19c9a;
							cursor:default;
						}
						
						>.code-rest-btn.disable:hover{
							background: #a19c9a;
							cursor:default;
						}
					}
				}
				
			}
		}
		>.body{
			height: calc(100% - 40px );
			>.edit{
				height: 100%;
				height: calc(100% - 400px );
				:deep(.CodeMirror-wrap pre) { word-break: break-word; }
				:deep(.CodeMirror) { height: 400px; width: 400px; border: 1px solid #ddd; }
				:deep(.CodeMirror-scroll) { max-height: 400px; width:400px; }
				:deep(.CodeMirror pre) { display:inline-block; padding-left: 7px; line-height: 1.25; }
				
				:deep(.ͼo) {
				    color: #abb2bf;
					background: var(--edit-color)
				}
				
				:deep(.ͼo .cm-gutters) {
					background-color:  var(--editor-color);
					color: #7d8799;
					border: none;
				}
				:deep(.ͼ4 .cm-line) {
				    caret-color: var(--edit-blue) !important;
				}
				
				:deep(.ͼo .cm-content) {
				    caret-color: var(--edit-blue);
				}
				
				:deep(.CodeMirror-wrap pre.CodeMirror-line){
				    word-wrap: break-word; 
				    white-space: pre-wrap;
				    word-break: normal;
				}
				
				:deep(.CodeMirror-wrap pre.CodeMirror-line-like) {
				    word-wrap: break-word; 
				    white-space: pre-wrap;
				    word-break: normal;
				}
				
				:deep(.ͼo .cm-content){
					width: 355px;
				}
				
				:deep(.cm-line){
					width: calc(var(--size) - 35px);
				}
				
				:deep(.cm-line span){
				    word-wrap: break-word;
				    white-space: pre-wrap;
				    word-break: normal;
				}
				:deep(.ͼ1 .cm-scroller){
					overflow: hidden;
				}
			}
			>.log{
				height:400px;
				>.head{
					border-bottom: 1px solid #373c54;
					border-top: 1px solid #373c54;
					background-color: #2a2d3e;
					height: 2.5rem;
					>div{
						padding: 0.3125rem;
						>span{
							border-left-width: 3px!important;
							padding-left: 8px!important;
							height: 16px;
							line-height: 17px;
							font-size: 13px;
							color: #ccc;
							-webkit-box-sizing: border-box;
							box-sizing: border-box;
							white-space: nowrap;
							border-left: 2px solid #0080ff;
							margin-left: 8px;
							padding-left: 3px;
						}
						>div{
							float: right;
							>span{
								color: #ccc;
								cursor: pointer;
								font-size: 14px;
							}
						}
					}
				}
				>.log-content{
					color: #ccc;
					padding: 0.3125rem;
					height: 100%;
					overflow: hidden;
					.log-li{
						border-bottom: 1px solid rgba(255,255,255,0.2);
					}
				}
			}
			
		}
		
	}
</style>